/*
Andrew Furry
b785w997
C++ project
starMap.cpp
Description: This program will go out to the Internet and gather a list of all named stars in the universe and the information given on each one, 
compiling them into a list of star objects. The user will be given several options: They can find stars that they have on the list, view the info on the given 
star, remove stars from the list, and calculate how long it will take for a person to travel to a specified star and back giving their constant speed 
(not exceeding the speed of light of course).

Class: Star
Description: This class will create Star objects that will be put into a list and contain info upon each star that is found on the website. The info will 
encompass the star's name, the constellation it is in, and the distance it is in light-years from the Earth.
Pre: Can be given the values of the name, constellation, distance, and time (will be used in CalcTime)
Post: Creates and returns a star object
Code:
   Default constructor: Creates the object, doesn't set it to anything
   Initializer constructor: Sets the classes values to ones given to it (time won't be set)
   CalcTime: This method will calculate the time it takes to get from Earth to the selected star and back
   Pre: will be given a velocity by the user
   Post: sets the time
   code:
      if given vel is over 3x10^8 (speed of light):
         print an appropriate error
      else
         set time = (distance / given vel) * 2 (later changed to ((c - vel) + c) * distance / c where c is the speed of light)

Function: GetPage
Description: Uses the Boost/cpp-netlib library (if it works) to aquire and parse a given webpage into a 'response' type variable. It will then return the 
response.
Pre: None
Post: a response
Code:
   create a Boost client and request
   get the request via the address of the site
   create and set the response = the request through the client
   return the response

Function: GatherStars
Desc: This will gather information off of the page it is passed and the name of the star. It will then store the information in a temperary linked list so the 
user can perform operations on those stars that they searched for.
Pre: List of constellations from getPage, linked list
Post: none
Code:
   find the star name on the response:
   create a sdt::string stream and vector of the request
   while std::getline is not the end of file
      for (i=0; std::getline.len >= i; i++)
         itterate through the line
         if it = ":
            if starName[0] = itterator[0]
               if starName[1] = itterator[1]
                  if starName[2] = itterator[2]
                     i = 2
                     while itterator < starName.len
                        itterator[i] = starName[i]
                        i++
   Find distance from Earth based on chars away from name
   set it equal to distance
   create a star object using found data
   add star to given linked list

Function: ViewInfo
Desc: This will display the info found in GatherStars
Pre: Star object
Post: Info on star
Code:
   print constellation, name, the distance from Earth, and the time it would take to travel there and back

Function: Main
Desc: Gets input from the user, creates a linked list of stars, calls appropriate functions based on user input
Pre: none
Post: list of stars
Code:
   create an empty linked list
   while input is not exit
      get constellation name from user
      call getpage and get the response
      use a similar code to GatherStar's nested loops to find the constellation name on the page
      get the star name from the user
      call gatherstars passing the list, star name, and constellation
      display info on the star
   free the list

*/

#include <boost/network/protocol/http/client.hpp>
#include <string>
#include <iostream>
using namespace std;
#include <star.cpp>
#include <star.hpp>
using namespace boost::network;

typedef headers_range<http_client::response>::type response_headers; //Typedef for reading a 'response' type file

namespace boost //A typedef for the kind of webpage we will be pulling of the Internet
{
   namespace network
   {
      namespace http
      {
         typedef basic_client<tags::http_default_8bit_tcp_resolve,1,1>
            client;
      }
   }
}

response GetPage(std::string constel)
{
   http::client cli;   //uses Boost to get the web page and store it in a response
   http::client::request req;
   req << boost::network::header("en.wikipedia.org/wiki/List_of_starts_in_" + constel);
   http::client::response resp = cli.get(req);

   //std::cout << body(resp);

   return resp;
}

void GatherStars(response page, std::string constel, std::tring starn, Node<Star> *lis)
{
   Star *newStar;
   Node<Star> *newNode;
   std::string tempName, tempD;
   double tempDist;
   response_headers headers_ = headers(page);
   for (iterator iter = headers_.begin(); iter != headers_.end(); ++iter) 
   {
      //std::cout << iter->first << ": " << iter->second << std::endl;
      if (*iter == starn.at(0))  //Tests to see if the iterator has found the star
      {                          //name or not by testing the first three letters of the given name
         tempName.push_back(*iter);
         iter++;
         if (*iter == starn.at(1))
         {
            tempName.push_back(*iter);
            iter++;
            if (*iter == starn.at(2))  //If the first three letters match, it will find the rest
            {
               while (iter != starn.end())
               {
                  tempName.push_back(*iter);
                  iter++;
               }
               
               iter = iter + 200; //Moves the buffer to where the distance is on the table (the lable is only at the top of the table)
               while (iter != headers_.end())   //finds the distance in lightyears by searching for integers instead of specific characters
               {
                  if (std::isdigit(*iter))
                  {
                     tempD = push_back(*iter);
                     iter++
                     if (std::isdigit(*iter))
                     {
                        while(std::isdigit(*iter))
                        {
                           tempD = push_back(*iter);
                           iter++;
                        }
                     } else
                        tempD.clear();
                  }
               }
            } else   //if the last letters don't match, the temporary star name holder is cleared
               tempName.clear();
         } else
            tempName.clear();
      }
   }
   
   if (tempName != NULL && tempD != NULL) //checks to see if the searcher found anything
      tempDist = stoi(tempD);
   else  //if not, returns an error
   {
      std::cout << "Error, star not found in database.";
      exit(1);
   }
   
   newStar = new Star(starn, constel, tempDist);   //creates a new star object with the data found/given
   newNode = new Node(newStar); //creates a linked list node with that star object
   if (lis.nextNode() != NULL) //checks to see if the list has anything on it yet
      lis.InsertNode(newNode->link); //if it does, it adds the node to the given linked list
   else
      lis.GetNode(newStar); //if it doesn't, it makes the star the head
   
}

void ViewInfo(Star slectedStar)  //displays the info on the given star
{
   std::cout << selectedStar->name;
   std::cout << selectedStar->constellation;
   std::cout << selectedStar->dist;
}

int main(void)
{
   std::string constName, starName;
   Node<Star> *list;
   response page;
   int selection;
   double velocity;
   
   list = new Node();   //creates a linked list for the stars
   
   while(selection != 0)   //lets the user input their choice
   {
      std::cout << "Please make a selection: \n1- Add a star to the list\n2-Delete star on the list\n3- View info on star on the list\n4- Calculate the time to get to a given star given the velocity\n0- Exit";
      std::cin >> selection;
      
      if (selection == 1)  //adds a star to the list
      {
         std::cout << "Please input a constellation name('exit' to end): ";
         std::cin >> constName;
         std::cout << "Please input a name of a star in that constellation: ";
         std::cin >> starName;
      
         page = GetPage();
         GatherStars(page, constName, starName, list);
         
         std::cout << "Star " << starName << " was added to the list!" << endl;
      } else if (selection == 2) //deletes a star from the list
      {
         Node<Star> tempNode;
         tempNode = list.DeleteNode();
         if (tempNode != NULL);
            std::cout << tempNode->data->name << " was deleted from the list." << endl;
         else
            std::cout << "Error, star not found on list" << endl;
            
      } else if (selection == 3) //shows info on the star
         ViewInfo(list.data);
      else if (selection == 4)   //calculates the time to get to the star
      {
         std::cout << "Please input the velocity you would like to travel at in m/s: ";
         std::cin >> velocity;
         std::cout << "It would take " << list->data.CalcTime(velocity) << " lightyears to get to the star " list->data->name << endl;
      } else if (selection == 0)
         std::cout << "Thank you for using the StarFinder!" << endl; //ends the program
      else
         std::cout << "Invalid input, please try again." << endl; //message for invalid input
   
   }
   
}

